/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.annotation;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Predicate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.Location;
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ConfigurationCondition.ConfigurationPhase;
import org.springframework.context.annotation.DeferredImportSelector.Group;
import org.springframework.core.NestedIOException;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.core.io.support.ResourcePropertySource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

/**
 * 核心功能：解析@Configuration类及其注解、父类、@Import/@Bean等内容，将其封装为ConfigurationClass对象集合。
 * 核心流程：
 * 1. 根据BeanDefinition的类型，选择不同的解析入口（Class对象、注解元数据、类名）。
 * 2. 检查@Configuration类是否被条件注解跳过。
 * 3. 解析父类和内部类的@Configuration结构。
 * 4. 解析@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、接口默认方法。
 * 5. 将解析后的ConfigurationClass对象存储在configurationClasses集合中。
 * <p>
 * 在Spring框架中的作用：
 * - 将@Configuration类抽象为ConfigurationClass，形成Spring对配置类解析的统一模型。
 * - 支撑@Import、自动化配置、条件装配等高级功能。
 * - 配合ConfigurationClassBeanDefinitionReader注册BeanDefinition。
 * <p>
 * Parses a {@link Configuration} class definition, populating a collection of
 * {@link ConfigurationClass} objects (parsing a single Configuration class may result in
 * any number of ConfigurationClass objects because one Configuration class may import
 * another using the {@link Import} annotation).
 *
 * <p>This class helps separate the concern of parsing the structure of a Configuration
 * class from the concern of registering BeanDefinition objects based on the content of
 * that model (with the exception of {@code @ComponentScan} annotations which need to be
 * registered immediately).
 *
 * <p>This ASM-based implementation avoids reflection and eager class loading in order to
 * interoperate effectively with lazy class loading in a Spring ApplicationContext.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @author Phillip Webb
 * @author Sam Brannen
 * @author Stephane Nicoll
 * @see ConfigurationClassBeanDefinitionReader
 * @since 3.0
 */
class ConfigurationClassParser {

	// 默认的 PropertySourceFactory，用于处理 @PropertySource 注解
	private static final PropertySourceFactory DEFAULT_PROPERTY_SOURCE_FACTORY = new DefaultPropertySourceFactory();

	// 默认的排除过滤器：跳过核心 Java 注解和 Spring 自身的常用注解
	private static final Predicate<String> DEFAULT_EXCLUSION_FILTER = className ->
			(className.startsWith("java.lang.annotation.") || className.startsWith("org.springframework.stereotype."));

	// DeferredImportSelector 的排序规则，使用 Spring 的 AnnotationAwareOrderComparator 排序
	private static final Comparator<DeferredImportSelectorHolder> DEFERRED_IMPORT_COMPARATOR =
			(o1, o2) -> AnnotationAwareOrderComparator.INSTANCE.compare(o1.getImportSelector(), o2.getImportSelector());


	// 日志工具
	private final Log logger = LogFactory.getLog(getClass());

	// 读取类元数据的工厂，支持 ASM 字节码读取
	private final MetadataReaderFactory metadataReaderFactory;

	// 处理配置类解析过程中的问题（错误/警告）
	private final ProblemReporter problemReporter;

	// Spring 的运行环境，保存属性、配置文件等信息
	private final Environment environment;

	// Spring 的资源加载器，用于加载 classpath 或文件系统中的资源
	private final ResourceLoader resourceLoader;

	// Bean 定义注册器，用于向 Spring 容器中注册解析出的 BeanDefinition
	private final BeanDefinitionRegistry registry;

	// 用于解析 @ComponentScan 注解的解析器
	private final ComponentScanAnnotationParser componentScanParser;

	// 条件评估器，用于解析 @Conditional 注解，决定是否跳过某些配置类或 Bean
	private final ConditionEvaluator conditionEvaluator;

	// 保存所有已经解析过的 ConfigurationClass，避免重复解析
	private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();

	// 保存已知的父类配置类，避免重复处理继承关系
	private final Map<String, ConfigurationClass> knownSuperclasses = new HashMap<>();

	// 已经加载的 @PropertySource 的名称列表，用于避免重复加载
	private final List<String> propertySourceNames = new ArrayList<>();

	// 导入栈（处理 @Import 注解时，用于检测循环导入）
	private final ImportStack importStack = new ImportStack();

	// 处理 DeferredImportSelector 的辅助类，延迟处理导入逻辑
	private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();

	// Object 类的 SourceClass 封装，用作基准（比如递归解析父类时的终止条件）
	private final SourceClass objectSourceClass = new SourceClass(Object.class);


	/**
	 * Create a new {@link ConfigurationClassParser} instance that will be used
	 * to populate the set of configuration classes.
	 */
	public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,
									ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader,
									BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {

		this.metadataReaderFactory = metadataReaderFactory;
		this.problemReporter = problemReporter;
		this.environment = environment;
		this.resourceLoader = resourceLoader;
		this.registry = registry;
		this.componentScanParser = new ComponentScanAnnotationParser(
				environment, resourceLoader, componentScanBeanNameGenerator, registry);
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
	}


	/**
	 * 解析一组配置类的 BeanDefinition，并对 @Import、@ComponentScan、@Bean 等注解进行处理。
	 * <p>
	 * 核心功能：
	 * 1. 遍历传入的 BeanDefinitionHolder 集合 configCandidates。
	 * 2. 根据 BeanDefinition 的类型（AnnotatedBeanDefinition、AbstractBeanDefinition 或普通 className）
	 * 调用不同的 parse 重载方法，最终都会进入 processConfigurationClass() 做深度解析。
	 * 3. 对 DeferredImportSelector 进行处理（延迟导入的配置类），保证在其他配置类解析完成后再执行。
	 * <p>
	 * 主要逻辑：
	 * 1）循环每个配置类 BD：
	 * - 如果是 AnnotatedBeanDefinition → 获取注解元数据进行解析
	 * - 如果是 AbstractBeanDefinition 且有 Class 对象 → 直接解析 Class
	 * - 否则 → 根据类名字符串解析
	 * 2）解析过程中可能抛出异常：
	 * - BeanDefinitionStoreException → 直接抛出
	 * - 其他异常 → 封装为 BeanDefinitionStoreException 并抛出
	 * 3）DeferredImportSelectorHandler.process()：
	 *    - 所有普通配置类解析完成后才处理 DeferredImportSelector
	 *    - 支持条件性导入其他配置类或 BeanDefinition
	 *    - **⚡️Spring Boot 自动配置的核心入口**
	 *        - Spring Boot 的自动配置类（META-INF/spring.factories 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports）
	 *          本质上就是通过 `@EnableAutoConfiguration` → `AutoConfigurationImportSelector` → 作为 `DeferredImportSelector` 注册到这里。
	 *        - 由于是 **延迟处理**，它会在用户定义的配置类（`@Configuration`）都加载完后再统一加载自动配置类，以保证用户配置优先、自动配置兜底的原则。
	 *
	 * @param configCandidates
	 */
	public void parse(Set<BeanDefinitionHolder> configCandidates) {
		// 循环遍历configCandidates
		for (BeanDefinitionHolder holder : configCandidates) {
			// 获取BeanDefinition
			BeanDefinition bd = holder.getBeanDefinition();
			// 根据BeanDefinition类型的不同，调用parse不同的重载方法，实际上最终都是调用processConfigurationClass()方法
			try {
				// 注解类型
				if (bd instanceof AnnotatedBeanDefinition) {
					parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
				}
				// 有class对象的
				else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
					parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
				} else {
					parse(bd.getBeanClassName(), holder.getBeanName());
				}
			} catch (BeanDefinitionStoreException ex) {
				throw ex;
			} catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
			}
		}

		// 处理 DeferredImportSelector（延迟导入选择器）
		// - 核心作用：Spring Boot 自动配置入口
		// - AutoConfigurationImportSelector（@EnableAutoConfiguration 的实现）就是通过这里触发的
		// - 设计目的：在用户配置类都完成解析后，统一加载自动配置类，避免自动配置覆盖用户自定义配置
		this.deferredImportSelectorHandler.process();
	}

	/**
	 * 根据 className 和 beanName 解析配置类，适用于只有类名的情况（ASM 方式读取字节码）
	 *
	 * @param className
	 * @param beanName
	 * @throws IOException
	 */
	protected final void parse(@Nullable String className, String beanName) throws IOException {
		Assert.notNull(className, "No bean class name for configuration class bean definition");
		// 通过 MetadataReader 读取 class 元数据（不需要加载类）
		MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
		// 委托给 processConfigurationClass 进行处理
		processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
	}

	/**
	 * 根据 Class 和 beanName 解析配置类，适用于已经加载了 Class 的情况
	 *
	 * @param clazz
	 * @param beanName
	 * @throws IOException
	 */
	protected final void parse(Class<?> clazz, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
	}

	/**
	 * 根据注解元数据和 beanName 解析配置类，适用于已经有 AnnotationMetadata 的情况
	 *
	 * @param metadata
	 * @param beanName
	 * @throws IOException
	 */
	protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
		processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
	}

	/**
	 * Validate each {@link ConfigurationClass} object.
	 *
	 * @see ConfigurationClass#validate
	 */
	public void validate() {
		for (ConfigurationClass configClass : this.configurationClasses.keySet()) {
			configClass.validate(this.problemReporter);
		}
	}

	public Set<ConfigurationClass> getConfigurationClasses() {
		return this.configurationClasses.keySet();
	}

	/**
	 * 处理并解析一个配置类（核心调度方法）
	 * <p>
	 * 主要作用：
	 * 1. 判断是否需要跳过配置类（例如 @Conditional 条件不满足的情况）
	 * 2. 处理重复的配置类：
	 * - 如果同一个配置类被多次 import，则合并 importedBy 信息
	 * - 如果有显式配置类（非 import），则覆盖之前的 import 定义
	 * 3. 递归解析配置类及其父类（除开 java.* 的父类）
	 * - 包装成 SourceClass（统一入口，不管是 Class 对象还是 ASM 元数据）
	 * - 调用 doProcessConfigurationClass 逐步解析其中的注解：
	 *
	 * @PropertySource / @ComponentScan / @Import / @Bean 方法 等
	 * 4. 将最终解析好的配置类放入 configurationClasses 缓存，供后续使用
	 */
	protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
		// 1. 判断是否需要跳过解析（例如 @Conditional 条件不满足时）
		if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
			return;
		}

		// 2. 处理重复的配置类（避免同一个类被多次解析）
		ConfigurationClass existingClass = this.configurationClasses.get(configClass);
		if (existingClass != null) {
			if (configClass.isImported()) {
				if (existingClass.isImported()) {
					// 如果新旧配置类都是通过 @Import 引入 → 合并 importBy 信息
					existingClass.mergeImportedBy(configClass);
				}
				// Otherwise ignore new imported config class; existing non-imported class overrides it.
				// 新的是 import，而旧的不是 → 忽略新配置类，保留已有的
				return;
			} else {
				// Explicit bean definition found, probably replacing an import.
				// Let's remove the old one and go with the new one.
				// 新的是显式配置类（非 import） → 覆盖旧的 import 定义
				this.configurationClasses.remove(configClass);
				this.knownSuperclasses.values().removeIf(configClass::equals);
			}
		}

		// Recursively process the configuration class and its superclass hierarchy.
		// 递归解析配置类及其父类（除开 java.* 包下的父类）
		// SourceClass：对类的统一包装（不管是 Class 还是 ASM MetadataReader）
		//   - 统一入口，屏蔽底层差异（反射 or ASM）
		//   - 提供统一的API获取注解、父类信息等
		SourceClass sourceClass = asSourceClass(configClass, filter);
		do {
			// 核心：对当前配置类上的注解进行解析（解析结果都会存入 configClass 对象中）
			// 包括但不限于：
			//   - @PropertySource   → 加载外部配置文件
			//   - @ComponentScan    → 注册扫描的包路径
			//   - @Import           → 递归触发，解析引入的其他配置类
			//   - @Bean             → 将方法声明的 Bean 注册成 BeanDefinition
			//
			// 返回值：当前类的父类（包装成 SourceClass）
			//   - 如果父类存在且不在 java.* 包下 → 返回父类 SourceClass，继续下一次循环
			//   - 如果父类是 java.* 包下的类（例如 Object） → 返回 null，循环结束
			//
			// 例如：
			//	- 第一次循环：解析 当前配置类。
			//	- 第二次循环：解析 父类。
			//	- 第三次循环：解析 父类的父类。
			//	- ……直到父类是 java.* 包下的类（例如 Object），返回 null，循环结束。
			//
			// 注意：
			// - 外层的 while 循环是“沿着父类链”逐层向上解析
			// - 内部的 @Import 解析逻辑则是“递归”，会分支处理额外引入的配置类
			// - 所有解析结果最终都会记录到 configClass 中，而不是依赖 sourceClass
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);

		// 4. 缓存解析完成的配置类，供后续使用
		//    - 将当前解析完成的 ConfigurationClass 放入 configurationClasses 缓存
		//    - 作用：
		//        1. 避免重复解析同一个配置类（防止递归或多次扫描同一类）
		//        2. 为后续注册阶段提供统一的数据源，
		//           后续 ConfigurationClassBeanDefinitionReader 会遍历这些 ConfigurationClass
		//           并根据其中收集的 @Bean 方法、扫描到的 BeanDefinition、导入的 XML 等信息
		//           真正生成并注册 BeanDefinition 到 IOC 容器
		//    - 总结：这是解析阶段与注册阶段的桥梁，把解析好的元数据交给后续阶段使用
		this.configurationClasses.put(configClass, configClass);

	}

	/**
	 * 核心方法：处理一个配置类（ConfigurationClass）
	 * 通过解析注解、内部类、成员方法等，构建完整的配置类模型。
	 * <p>
	 * 主要流程：
	 * 1. 处理内部类（@Configuration 内部类）
	 * 2. 解析 @PropertySource 注解，加载外部 properties
	 * 3. 解析 @ComponentScan / @ComponentScans，扫描包下的 Bean 并递归处理
	 * 4. 解析 @Import 注解，导入配置类或 ImportSelector、ImportBeanDefinitionRegistrar
	 * 5. 解析 @ImportResource 注解，导入 XML 配置文件
	 * 6. 解析 @Bean 方法，注册为 BeanMethod
	 * 7. 处理接口默认方法上的 @Bean（Java 8 特性）
	 * 8. 解析父类（如果父类不是 JDK 内置类），并递归处理
	 * <p>
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
	 *
	 * @param configClass the configuration class being build
	 * @param sourceClass a source class
	 * @return the superclass, or {@code null} if none found or previously processed
	 */
	@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
		// @Configuration 本身继承了 @Component，所以配置类也会被识别为组件类
		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// 递归处理配置类中的内部类
			// 说明：如果配置类有静态内部类（并且也使用了 @Configuration 或其他候选注解），
			// 那么这些内部类同样可能是配置类，需要通过 processMemberClasses 方法继续解析，
			// 确保内部类中的 @Bean 方法、@Import 等也能被正确注册到容器中。
			processMemberClasses(configClass, sourceClass, filter);
		}

		// Process any @PropertySource annotations
		// 处理配置类上的 @PropertySource 注解
		// 作用：加载指定的 properties 文件，并把属性添加到 Spring 的 Environment 中，
		//      这样后续就可以通过 @Value 或 Environment.getProperty() 来使用这些配置。
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				// 如果当前 Environment 可配置（支持属性源管理），则解析并加载 @PropertySource 中定义的资源文件
				processPropertySource(propertySource);
			} else {
				// 否则忽略，并打印提示日志
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// Process any @ComponentScan annotations
		// 处理配置类上的 @ComponentScan 或 @ComponentScans 注解
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				// 1. 执行包扫描
				//    根据 @ComponentScan 配置的 basePackages/basePackageClasses 等信息，
				//    扫描指定包及其子包下的所有候选组件类，并将其解析为 BeanDefinition。
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

				// 2. 处理扫描得到的 BeanDefinition
				//    如果某个类本身又是一个配置类（比如也加了 @Configuration、@ComponentScan 等），
				//    则需要递归调用 parse 方法继续解析，保证嵌套配置类也能被处理。
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}

					// 判断该类是否是配置类候选（FULL/LITE）
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						// 如果是配置类，递归解析
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// Process any @Import annotations
		// 处理 @Import 注解
		//    如果配置类上标注了 @Import，会导入指定的类。
		//    可能是普通的配置类（再次递归解析）、ImportSelector、ImportBeanDefinitionRegistrar 等，
		//    通过 processImports 方法统一处理。
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// Process any @ImportResource annotations
		// 处理 @ImportResource 注解
		//    如果配置类上标注了 @ImportResource，可以导入 XML 配置文件。
		//    - locations 指定 XML 配置文件路径
		//    - reader 指定 BeanDefinitionReader，用来解析 XML
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				// 1 支持占位符解析，例如 ${user.dir}/app-context.xml
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				// 2 保存到当前配置类的 importedResources 集合，后续统一处理
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// Process individual @Bean methods
		// 处理配置类中的 @Bean 方法
		// 1. 扫描当前配置类，获取所有标注了 @Bean 的方法元数据（MethodMetadata）。
		// 2. 将每个 @Bean 方法封装成 BeanMethod 对象，并保存到 ConfigurationClass 中。
		//    注意：这一步只是“收集信息”，并不会立即生成 BeanDefinition。
		// 3. 在后续解析阶段（ConfigurationClassBeanDefinitionReader），
		//    Spring 会根据这些 BeanMethod 对象，真正把 @Bean 方法转化为 BeanDefinition 并注册到容器。
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// Process default methods on interfaces
		// 处理接口的默认方法实现，从jdk8开始，接口中的方法可以有自己的默认实现，因此如果这个接口的方法加了@Bean注解，也需要被解析
		processInterfaces(configClass, sourceClass);

		// Process superclass, if any
		// 解析父类，如果被解析的配置类继承了某个类，那么配置类的父类也会被进行解析
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				// Superclass found, return its annotation metadata and recurse
				return sourceClass.getSuperClass();
			}
		}

		// No superclass -> processing is complete
		return null;
	}

	/**
	 * Register member (nested) classes that happen to be configuration classes themselves.
	 * 处理配置类的内部类（nested class）
	 * 如果内部类本身也是配置类，则递归进行解析。
	 * <p>
	 * 主要流程：
	 * 1. 获取当前配置类的所有内部类
	 * 2. 过滤出符合条件的候选配置类
	 * - 满足 ConfigurationClassUtils.isConfigurationCandidate
	 * - 排除自身（避免死循环）
	 * 3. 对候选类进行排序（@Order 生效）
	 * 4. 遍历候选类：
	 * - 检查是否存在循环导入（importStack 检测）
	 * - 将当前配置类入栈，递归调用 processConfigurationClass 继续解析内部类
	 * - 解析完成后出栈
	 */
	private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass,
									  Predicate<String> filter) throws IOException {

		// 找到内部类，内部类中也可能是一个配置类
		Collection<SourceClass> memberClasses = sourceClass.getMemberClasses();
		// 如果不等于空的话
		if (!memberClasses.isEmpty()) {
			List<SourceClass> candidates = new ArrayList<>(memberClasses.size());
			// 循环判断内部类是不是配置类
			for (SourceClass memberClass : memberClasses) {
				if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
						!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
					candidates.add(memberClass);
				}
			}
			// 对配置类进行排序操作
			OrderComparator.sort(candidates);
			// 遍历符合规则的类
			for (SourceClass candidate : candidates) {
				if (this.importStack.contains(configClass)) {
					// 出现配置类循环导入，则直接报错
					this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
				} else {
					// 将配置类入栈
					this.importStack.push(configClass);
					try {
						// 调用processConfigurationClass方法，因为内部类中还可能包含内部类，所以需要在做循环解析，实际工作中是不会有这中情况的
						processConfigurationClass(candidate.asConfigClass(configClass), filter);
					} finally {
						// 解析完出栈
						this.importStack.pop();
					}
				}
			}
		}
	}

	/**
	 * Register default methods on interfaces implemented by the configuration class.
	 */
	private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
		// 找到配置类的所有接口，遍历接口
		for (SourceClass ifc : sourceClass.getInterfaces()) {
			// 找到含有@Bean注解的默认方法
			Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
			for (MethodMetadata methodMetadata : beanMethods) {
				if (!methodMetadata.isAbstract()) {
					// A default method or other concrete method on a Java 8+ interface...
					// 添加到集合中
					configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
				}
			}
			// 递归处理，因为接口可能存在父接口
			processInterfaces(configClass, ifc);
		}
	}

	/**
	 * 获取配置类中所有标注了 @Bean 的方法的元数据。
	 * 注意：为了保证方法的顺序稳定，Spring 尝试优先通过 ASM 解析 class 文件，
	 *      避免使用 Java 反射获取方法时顺序不确定的问题。
	 *
	 * Retrieve the metadata for all <code>@Bean</code> methods.
	 */
	private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
		// 1. 获取配置类的注解元数据
		AnnotationMetadata original = sourceClass.getMetadata();

		// 2. 通过元数据 API 找到所有 @Bean 注解的方法
		Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());

		// 3. 如果有多个 @Bean 方法，且当前是基于反射的元数据（StandardAnnotationMetadata），
		//    则尝试使用 ASM 来重新读取 class 文件，保证方法顺序的确定性。
		if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
			// Try reading the class file via ASM for deterministic declaration order...
			// Unfortunately, the JVM's standard reflection returns methods in arbitrary
			// order, even between different runs of the same application on the same JVM.
			try {
				// 3.1 使用 ASM 从字节码文件重新读取注解元数据
				AnnotationMetadata asm =
						this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
				Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());

				// 3.2 如果 ASM 读取到的方法数量 >= 反射获取的方法数量，则尝试按 ASM 的顺序重排
				if (asmMethods.size() >= beanMethods.size()) {
					Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
					for (MethodMetadata asmMethod : asmMethods) {
						for (MethodMetadata beanMethod : beanMethods) {
							if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
								selectedMethods.add(beanMethod);
								break;
							}
						}
					}

					// 3.3 如果所有方法都能匹配上，则使用按 ASM 顺序排列后的结果
					if (selectedMethods.size() == beanMethods.size()) {
						beanMethods = selectedMethods;
					}
				}
			} catch (IOException ex) {
				// 3.4 如果 ASM 解析失败，退回用反射得到的 beanMethods
				logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
			}
		}

		// 4. 返回最终的 @Bean 方法集合（顺序已尽可能稳定）
		return beanMethods;
	}


	/**
	 * 根据 @PropertySource 注解的属性，加载对应的配置文件，
	 * 并将其作为 PropertySource 添加到 Spring 的 Environment 中。
	 * <p>
	 * Process the given <code>@PropertySource</code> annotation metadata.
	 *
	 * @param propertySource metadata for the <code>@PropertySource</code> annotation found
	 * @throws IOException if loading a property source failed
	 */
	private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
		// 1. 获取注解中的 name 属性（可选，用来给属性源起个名字）
		String name = propertySource.getString("name");
		if (!StringUtils.hasLength(name)) {
			name = null;
		}

		// 2. 获取注解中的 encoding 属性（可选，指定文件的字符编码）
		String encoding = propertySource.getString("encoding");
		if (!StringUtils.hasLength(encoding)) {
			encoding = null;
		}

		// 3. 获取注解中的 value 属性（必须，配置文件的路径，可以是多个）
		String[] locations = propertySource.getStringArray("value");
		Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");

		// 4. 是否忽略找不到资源的情况
		boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

		// 5. 获取注解中的 factory 属性（用于自定义解析属性文件的工厂类）
		Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
		PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
				DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));

		// 6. 遍历每一个配置文件路径，依次加载
		for (String location : locations) {
			try {
				// 6.1 先解析路径中的占位符（比如 ${user.home}/app.properties）
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);

				// 6.2 将路径转换成 Resource 对象（Spring 统一的资源抽象，可以是文件、classpath、URL 等）
				Resource resource = this.resourceLoader.getResource(resolvedLocation);

				// 6.3 使用 PropertySourceFactory 创建 PropertySource，并添加到 Environment 中
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			// 7. 处理资源找不到或无法解析的异常
			catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
				if (ignoreResourceNotFound) {
					// 如果配置了 ignoreResourceNotFound = true，则忽略并打印提示
					if (logger.isInfoEnabled()) {
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				} else {
					// 否则抛出异常，中断启动
					throw ex;
				}
			}
		}
	}

	/**
	 * 将新的 PropertySource 添加到 Environment 中的 PropertySources 列表里。
	 * 需要处理以下情况：
	 *  1. 如果已经有同名的 PropertySource，则合并（用 CompositePropertySource 包装）。
	 *  2. 如果是第一次添加，则放在最后（最低优先级）。
	 *  3. 否则插入到之前已处理过的 PropertySource 之前，保证优先级顺序。
	 */
	private void addPropertySource(PropertySource<?> propertySource) {
		String name = propertySource.getName();
		MutablePropertySources propertySources =
				((ConfigurableEnvironment) this.environment).getPropertySources();

		// --- 情况 1：已有同名 PropertySource ---
		if (this.propertySourceNames.contains(name)) {
			PropertySource<?> existing = propertySources.get(name);
			if (existing != null) {
				// 如果是 ResourcePropertySource，则替换为带资源名称的版本（更可读）
				PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ?
						((ResourcePropertySource) propertySource).withResourceName() : propertySource);

				// 如果已存在的是 CompositePropertySource，直接往前面加新 source
				if (existing instanceof CompositePropertySource) {
					((CompositePropertySource) existing).addFirstPropertySource(newSource);
				}
				// 否则，把现有的和新的都合并成 CompositePropertySource
				else {
					if (existing instanceof ResourcePropertySource) {
						existing = ((ResourcePropertySource) existing).withResourceName();
					}
					CompositePropertySource composite = new CompositePropertySource(name);
					composite.addPropertySource(newSource);
					composite.addPropertySource(existing);
					propertySources.replace(name, composite);
				}
				return;
			}
		}

		// --- 情况 2：第一次添加 PropertySource ---
		// 放到最后，优先级最低
		if (this.propertySourceNames.isEmpty()) {
			propertySources.addLast(propertySource);
		}
		// --- 情况 3：已经有其它 PropertySource ---
		// 插到已处理过的最前面
		else {
			String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
			propertySources.addBefore(firstProcessed, propertySource);
		}
		// 记录已经添加过的 propertySource 名称，避免重复
		this.propertySourceNames.add(name);
	}


	/**
	 * 获取给定类及其所有元注解（meta-annotations）中声明的 {@code @Import} 注解所引入的类。
	 * Returns {@code @Import} class, considering all meta-annotations.
	 *
	 * <p>例如：一个 {@code @Configuration} 类可能直接声明了 {@code @Import}，
	 * 同时它标注的 {@code @EnableXXX} 注解中也可能包含 {@code @Import}，
	 * 此方法会统一收集这些信息。
	 *
	 * @param sourceClass 要分析的类（可能是配置类或注解类）
	 * @return 收集到的所有 {@code @Import} 对应的类集合
	 * @throws IOException 如果在读取类元数据时发生错误
	 *
	 */
	private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
		// 创建集合，存储包含@Import注解的类
		Set<SourceClass> imports = new LinkedHashSet<>();
		// 创建集合，为了实现递归调用
		Set<SourceClass> visited = new LinkedHashSet<>();
		// 收集@Import注解的类
		collectImports(sourceClass, imports, visited);
		return imports;
	}

	/**
	 * 递归收集指定类及其元注解中声明的所有 {@code @Import} 引用。
	 * <p>与大多数元注解不同，{@code @Import} 允许在同一个类层级结构中多次出现，
	 * 且每个声明可能引入不同的配置类。因此不能只取第一个，需要完整遍历。
	 *
	 * <p>例如：一个 {@code @Configuration} 类可能包含直接的 {@code @Import}，
	 * 而它的某个 {@code @EnableXXX} 注解中也可能存在 {@code @Import}，
	 * 本方法会将两者的结果都收集起来。
	 *
	 * Recursively collect all declared {@code @Import} values. Unlike most
	 * meta-annotations it is valid to have several {@code @Import}s declared with
	 * different values; the usual process of returning values from the first
	 * meta-annotation on a class is not sufficient.
	 * <p>For example, it is common for a {@code @Configuration} class to declare direct
	 * {@code @Import}s in addition to meta-imports originating from an {@code @Enable}
	 * annotation.
	 *
	 * @param sourceClass the class to search，当前要检查的类
	 * @param imports     the imports collected so far，已经收集到的 {@code @Import} 类集合
	 * @param visited     used to track visited classes to prevent infinite recursion，已访问过的类集合，用于防止无限递归
	 * @throws IOException if there is any problem reading metadata from the named class，如果在读取类元数据时发生错误
	 *
	 */
	private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
			throws IOException {

		if (visited.add(sourceClass)) {
			for (SourceClass annotation : sourceClass.getAnnotations()) {
				String annName = annotation.getMetadata().getClassName();
				// 递归处理其他可能包含@Import的注解类
				if (!annName.equals(Import.class.getName())) {
					collectImports(annotation, imports, visited);
				}
			}
			// 获取Import注解的值
			imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
		}
	}

	/**
	 * 处理通过 {@code @Import} 注解引入的类。
	 * 该方法会判断每个被引入的类的类型，并根据不同的情况做不同的处理：
	 *   如果是 {@link ImportSelector}，则通过选择器逻辑决定需要导入的类
	 *   如果是 {@link DeferredImportSelector}，则延迟到所有配置类处理完毕后再导入
	 *   如果是 {@link ImportBeanDefinitionRegistrar}，则交由其注册额外的 Bean 定义
	 *   否则，将其作为一个普通的 {@code @Configuration} 配置类进行处理
	 * 同时，该方法会处理循环导入的问题，并使用栈结构来跟踪导入链路。
	 *
	 * @param configClass             当前正在处理的配置类
	 * @param currentSourceClass      当前配置类对应的 {@link SourceClass}
	 * @param importCandidates        待处理的候选导入类（由 @Import 指定）
	 * @param exclusionFilter         类过滤器，用于排除不需要导入的类
	 * @param checkForCircularImports 是否检查循环导入
	 */
	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		// 如果使用@Import注解修饰的类集合为空，那么直接返回
		if (importCandidates.isEmpty()) {
			return;
		}
		// 通过一个栈结构解决循环引入
		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		} else {
			// 添加到栈中，用于处理循环引入的问题
			this.importStack.push(configClass);
			try {
				// 遍历每一个@Import注解的类
				for (SourceClass candidate : importCandidates) {
					// 检验配置类Import引入的类是否是ImportSelector子类
					if (candidate.isAssignable(ImportSelector.class)) {
						// Candidate class is an ImportSelector -> delegate to it to determine imports
						// 候选类是一个导入选择器->委托来确定是否进行导入
						Class<?> candidateClass = candidate.loadClass();
						// 通过反射生成一个ImportSelect对象
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						// 获取选择器的额外过滤器
						Predicate<String> selectorFilter = selector.getExclusionFilter();
						if (selectorFilter != null) {
							exclusionFilter = exclusionFilter.or(selectorFilter);
						}
						// 判断引用选择器是否是DeferredImportSelector接口的实例
						// 如果是则应用选择器将会在所有的配置类都加载完毕后加载
						if (selector instanceof DeferredImportSelector) {
							// 将选择器添加到deferredImportSelectorHandler实例中，预留到所有的配置类加载完成后统一处理自动化配置类
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						} else {
							// 获取引入的类，然后使用递归方式将这些类中同样添加了@Import注解引用的类
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							// 递归处理，被Import进来的类也有可能@Import注解
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					// 如果是实现了ImportBeanDefinitionRegistrar接口的bd
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						// 候选类是ImportBeanDefinitionRegistrar  -> 委托给当前注册器注册其他bean
						Class<?> candidateClass = candidate.loadClass();
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						/**
						 * 放到当前configClass的importBeanDefinitionRegistrars中
						 * 在ConfigurationClassPostProcessor处理configClass时会随之一起处理
						 */
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					} else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						// 候选类既不是ImportSelector也不是ImportBeanDefinitionRegistrar-->将其作为@Configuration配置类处理
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						/**
						 * 如果Import的类型是普通类，则将其当作带有@Configuration的类一样处理
						 * 将candidate构造为ConfigurationClass，标注为importedBy，意味着它是通过被@Import进来的
						 * 后面处理会用到这个判断将这个普通类注册进DefaultListableBeanFactory
						 */
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			} catch (BeanDefinitionStoreException ex) {
				throw ex;
			} catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
								configClass.getMetadata().getClassName() + "]", ex);
			} finally {
				this.importStack.pop();
			}
		}
	}

	private boolean isChainedImportOnStack(ConfigurationClass configClass) {
		if (this.importStack.contains(configClass)) {
			String configClassName = configClass.getMetadata().getClassName();
			AnnotationMetadata importingClass = this.importStack.getImportingClassFor(configClassName);
			while (importingClass != null) {
				if (configClassName.equals(importingClass.getClassName())) {
					return true;
				}
				importingClass = this.importStack.getImportingClassFor(importingClass.getClassName());
			}
		}
		return false;
	}

	ImportRegistry getImportRegistry() {
		return this.importStack;
	}


	/**
	 * Factory method to obtain a {@link SourceClass} from a {@link ConfigurationClass}.
	 */
	private SourceClass asSourceClass(ConfigurationClass configurationClass, Predicate<String> filter) throws IOException {
		AnnotationMetadata metadata = configurationClass.getMetadata();
		if (metadata instanceof StandardAnnotationMetadata) {
			return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass(), filter);
		}
		return asSourceClass(metadata.getClassName(), filter);
	}

	/**
	 * Factory method to obtain a {@link SourceClass} from a {@link Class}.
	 */
	SourceClass asSourceClass(@Nullable Class<?> classType, Predicate<String> filter) throws IOException {
		if (classType == null || filter.test(classType.getName())) {
			return this.objectSourceClass;
		}
		try {
			// Sanity test that we can reflectively read annotations,
			// including Class attributes; if not -> fall back to ASM
			for (Annotation ann : classType.getDeclaredAnnotations()) {
				AnnotationUtils.validateAnnotation(ann);
			}
			return new SourceClass(classType);
		} catch (Throwable ex) {
			// Enforce ASM via class name resolution
			return asSourceClass(classType.getName(), filter);
		}
	}

	/**
	 * Factory method to obtain a {@link SourceClass} collection from class names.
	 */
	private Collection<SourceClass> asSourceClasses(String[] classNames, Predicate<String> filter) throws IOException {
		List<SourceClass> annotatedClasses = new ArrayList<>(classNames.length);
		for (String className : classNames) {
			annotatedClasses.add(asSourceClass(className, filter));
		}
		return annotatedClasses;
	}

	/**
	 * Factory method to obtain a {@link SourceClass} from a class name.
	 */
	SourceClass asSourceClass(@Nullable String className, Predicate<String> filter) throws IOException {
		if (className == null || filter.test(className)) {
			return this.objectSourceClass;
		}
		if (className.startsWith("java")) {
			// Never use ASM for core java types
			try {
				return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader()));
			} catch (ClassNotFoundException ex) {
				throw new NestedIOException("Failed to load class [" + className + "]", ex);
			}
		}
		return new SourceClass(this.metadataReaderFactory.getMetadataReader(className));
	}


	@SuppressWarnings("serial")
	private static class ImportStack extends ArrayDeque<ConfigurationClass> implements ImportRegistry {

		private final MultiValueMap<String, AnnotationMetadata> imports = new LinkedMultiValueMap<>();

		public void registerImport(AnnotationMetadata importingClass, String importedClass) {
			this.imports.add(importedClass, importingClass);
		}

		@Override
		@Nullable
		public AnnotationMetadata getImportingClassFor(String importedClass) {
			return CollectionUtils.lastElement(this.imports.get(importedClass));
		}

		@Override
		public void removeImportingClass(String importingClass) {
			for (List<AnnotationMetadata> list : this.imports.values()) {
				for (Iterator<AnnotationMetadata> iterator = list.iterator(); iterator.hasNext(); ) {
					if (iterator.next().getClassName().equals(importingClass)) {
						iterator.remove();
						break;
					}
				}
			}
		}

		/**
		 * Given a stack containing (in order)
		 * <ul>
		 * <li>com.acme.Foo</li>
		 * <li>com.acme.Bar</li>
		 * <li>com.acme.Baz</li>
		 * </ul>
		 * return "[Foo->Bar->Baz]".
		 */
		@Override
		public String toString() {
			StringJoiner joiner = new StringJoiner("->", "[", "]");
			for (ConfigurationClass configurationClass : this) {
				joiner.add(configurationClass.getSimpleName());
			}
			return joiner.toString();
		}
	}


	private class DeferredImportSelectorHandler {

		@Nullable
		private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>();

		/**
		 * Handle the specified {@link DeferredImportSelector}. If deferred import
		 * selectors are being collected, this registers this instance to the list. If
		 * they are being processed, the {@link DeferredImportSelector} is also processed
		 * immediately according to its {@link DeferredImportSelector.Group}.
		 *
		 * @param configClass    the source configuration class
		 * @param importSelector the selector to handle
		 */
		public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
			DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
			if (this.deferredImportSelectors == null) {
				DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
				handler.register(holder);
				handler.processGroupImports();
			} else {
				this.deferredImportSelectors.add(holder);
			}
		}

		/**
		 * 处理所有收集到的 {@link DeferredImportSelector}，并触发延迟导入逻辑。
		 */
		public void process() {
			// 从属性中获取所有延迟导入选择器（DeferredImportSelector）
			List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
			this.deferredImportSelectors = null; // 防止重复处理

			try {
				if (deferredImports != null) {
					// 1. 创建分组处理器（GroupingHandler）
					//    - Spring Boot 的 AutoConfigurationImportSelector 会分到同一个分组（默认 AutoConfigurationGroup）
					DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();

					// 2. 排序：基于 @Order 或 Ordered 接口，保证执行顺序确定
					deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);

					// 3. 注册到分组处理器
					//    - 相同分组的 DeferredImportSelector 会被聚合在一起
					deferredImports.forEach(handler::register);

					// 4. 核心步骤：处理分组导入（真正触发自动配置加载）
					//    - handler.processGroupImports()
					//    - 会调用 AutoConfigurationGroup → AutoConfigurationImportSelector
					//    - 读取 META-INF/spring.factories 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
					//    - 批量导入自动配置类（xxxAutoConfiguration）
					handler.processGroupImports();
				}
			} finally {
				// 重置列表，保证下次新的 DeferredImportSelector 可以再次收集
				this.deferredImportSelectors = new ArrayList<>();
			}
		}
	}


	private class DeferredImportSelectorGroupingHandler {

		private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>();

		private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>();

		public void register(DeferredImportSelectorHolder deferredImport) {
			Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup();
			DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
					(group != null ? group : deferredImport),
					key -> new DeferredImportSelectorGrouping(createGroup(group)));
			grouping.add(deferredImport);
			this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
					deferredImport.getConfigurationClass());
		}

		/**
		 * 处理分组后的 {@link DeferredImportSelector}，将自动配置类正式导入容器。
		 *
		 * 核心流程：
		 *   1. 遍历所有分组（每个 {@link DeferredImportSelectorGrouping} 对应一类延迟导入选择器，
		 *       Spring Boot 的自动配置选择器 {@code AutoConfigurationImportSelector} 默认会归入同一分组）。
		 *   2. 为每个分组获取排除过滤器 {@code exclusionFilter}，
		 *       用于跳过不需要加载的候选配置类（例如被 spring.autoconfigure.exclude 配置排除的类）。
		 *   3. 调用 {@link DeferredImportSelectorGrouping#getImports()}：
		 *         这是读取自动配置候选类的核心步骤。
		 *         内部会加载 META-INF/spring.factories 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports。
		 *         同时应用条件注解（@ConditionalOnClass、@ConditionalOnMissingBean 等）。
		 *         最终返回需要导入的配置类列表。
		 *   4. 遍历返回的配置类：
		 *         找到对应的 {@link ConfigurationClass}。
		 *         调用 {@link #processImports(ConfigurationClass, SourceClass, Collection, Predicate, boolean)}，
		 *             将这些配置类进一步解析（例如配置类中可能再次声明 @Import）。
		 *         最终把这些类转换为 BeanDefinition 并注册到容器。
		 */
		public void processGroupImports() {
			for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
				Predicate<String> exclusionFilter = grouping.getCandidateFilter();
				// getImports 方法是读取自动化配置类的核心入口
				grouping.getImports().forEach(entry -> {
					ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
					try {
						// 配置类中可能包含 @Import 引入的类，通过此方法将其解析并注入容器
						processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter),
								Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)),
								exclusionFilter, false);
					}
					catch (BeanDefinitionStoreException ex) {
						throw ex;
					}
					catch (Throwable ex) {
						throw new BeanDefinitionStoreException(
								"Failed to process import candidates for configuration class [" +
										configurationClass.getMetadata().getClassName() + "]", ex);
					}
				});
			}
		}

		private Group createGroup(@Nullable Class<? extends Group> type) {
			Class<? extends Group> effectiveType = (type != null ? type : DefaultDeferredImportSelectorGroup.class);
			return ParserStrategyUtils.instantiateClass(effectiveType, Group.class,
					ConfigurationClassParser.this.environment,
					ConfigurationClassParser.this.resourceLoader,
					ConfigurationClassParser.this.registry);
		}
	}


	private static class DeferredImportSelectorHolder {

		private final ConfigurationClass configurationClass;

		private final DeferredImportSelector importSelector;

		public DeferredImportSelectorHolder(ConfigurationClass configClass, DeferredImportSelector selector) {
			this.configurationClass = configClass;
			this.importSelector = selector;
		}

		public ConfigurationClass getConfigurationClass() {
			return this.configurationClass;
		}

		public DeferredImportSelector getImportSelector() {
			return this.importSelector;
		}
	}


	private static class DeferredImportSelectorGrouping {

		private final DeferredImportSelector.Group group;

		private final List<DeferredImportSelectorHolder> deferredImports = new ArrayList<>();

		DeferredImportSelectorGrouping(Group group) {
			this.group = group;
		}

		public void add(DeferredImportSelectorHolder deferredImport) {
			this.deferredImports.add(deferredImport);
		}

		/**
		 * Return the imports defined by the group.
		 *
		 * @return each import with its associated configuration class
		 */
		public Iterable<Group.Entry> getImports() {
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				// 核心方法，在springboot中此方法会去SpringFactoriesLoader类中加载自动化配置类
				this.group.process(deferredImport.getConfigurationClass().getMetadata(),
						deferredImport.getImportSelector());
			}
			// 获取已经取得的配置类
			return this.group.selectImports();
		}

		public Predicate<String> getCandidateFilter() {
			Predicate<String> mergedFilter = DEFAULT_EXCLUSION_FILTER;
			for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
				Predicate<String> selectorFilter = deferredImport.getImportSelector().getExclusionFilter();
				if (selectorFilter != null) {
					mergedFilter = mergedFilter.or(selectorFilter);
				}
			}
			return mergedFilter;
		}
	}


	private static class DefaultDeferredImportSelectorGroup implements Group {

		private final List<Entry> imports = new ArrayList<>();

		@Override
		public void process(AnnotationMetadata metadata, DeferredImportSelector selector) {
			for (String importClassName : selector.selectImports(metadata)) {
				this.imports.add(new Entry(metadata, importClassName));
			}
		}

		@Override
		public Iterable<Entry> selectImports() {
			return this.imports;
		}
	}


	/**
	 * Simple wrapper that allows annotated source classes to be dealt with
	 * in a uniform manner, regardless of how they are loaded.
	 */
	private class SourceClass implements Ordered {

		private final Object source;  // Class or MetadataReader

		private final AnnotationMetadata metadata;

		public SourceClass(Object source) {
			this.source = source;
			if (source instanceof Class) {
				this.metadata = AnnotationMetadata.introspect((Class<?>) source);
			} else {
				this.metadata = ((MetadataReader) source).getAnnotationMetadata();
			}
		}

		public final AnnotationMetadata getMetadata() {
			return this.metadata;
		}

		@Override
		public int getOrder() {
			Integer order = ConfigurationClassUtils.getOrder(this.metadata);
			return (order != null ? order : Ordered.LOWEST_PRECEDENCE);
		}

		public Class<?> loadClass() throws ClassNotFoundException {
			if (this.source instanceof Class) {
				return (Class<?>) this.source;
			}
			String className = ((MetadataReader) this.source).getClassMetadata().getClassName();
			return ClassUtils.forName(className, resourceLoader.getClassLoader());
		}

		public boolean isAssignable(Class<?> clazz) throws IOException {
			if (this.source instanceof Class) {
				return clazz.isAssignableFrom((Class<?>) this.source);
			}
			return new AssignableTypeFilter(clazz).match((MetadataReader) this.source, metadataReaderFactory);
		}

		public ConfigurationClass asConfigClass(ConfigurationClass importedBy) {
			if (this.source instanceof Class) {
				return new ConfigurationClass((Class<?>) this.source, importedBy);
			}
			return new ConfigurationClass((MetadataReader) this.source, importedBy);
		}

		public Collection<SourceClass> getMemberClasses() throws IOException {
			Object sourceToProcess = this.source;
			if (sourceToProcess instanceof Class) {
				Class<?> sourceClass = (Class<?>) sourceToProcess;
				try {
					Class<?>[] declaredClasses = sourceClass.getDeclaredClasses();
					List<SourceClass> members = new ArrayList<>(declaredClasses.length);
					for (Class<?> declaredClass : declaredClasses) {
						members.add(asSourceClass(declaredClass, DEFAULT_EXCLUSION_FILTER));
					}
					return members;
				} catch (NoClassDefFoundError err) {
					// getDeclaredClasses() failed because of non-resolvable dependencies
					// -> fall back to ASM below
					sourceToProcess = metadataReaderFactory.getMetadataReader(sourceClass.getName());
				}
			}

			// ASM-based resolution - safe for non-resolvable classes as well
			MetadataReader sourceReader = (MetadataReader) sourceToProcess;
			String[] memberClassNames = sourceReader.getClassMetadata().getMemberClassNames();
			List<SourceClass> members = new ArrayList<>(memberClassNames.length);
			for (String memberClassName : memberClassNames) {
				try {
					members.add(asSourceClass(memberClassName, DEFAULT_EXCLUSION_FILTER));
				} catch (IOException ex) {
					// Let's skip it if it's not resolvable - we're just looking for candidates
					if (logger.isDebugEnabled()) {
						logger.debug("Failed to resolve member class [" + memberClassName +
								"] - not considering it as a configuration class candidate");
					}
				}
			}
			return members;
		}

		public SourceClass getSuperClass() throws IOException {
			if (this.source instanceof Class) {
				return asSourceClass(((Class<?>) this.source).getSuperclass(), DEFAULT_EXCLUSION_FILTER);
			}
			return asSourceClass(
					((MetadataReader) this.source).getClassMetadata().getSuperClassName(), DEFAULT_EXCLUSION_FILTER);
		}

		public Set<SourceClass> getInterfaces() throws IOException {
			Set<SourceClass> result = new LinkedHashSet<>();
			if (this.source instanceof Class) {
				Class<?> sourceClass = (Class<?>) this.source;
				for (Class<?> ifcClass : sourceClass.getInterfaces()) {
					result.add(asSourceClass(ifcClass, DEFAULT_EXCLUSION_FILTER));
				}
			} else {
				for (String className : this.metadata.getInterfaceNames()) {
					result.add(asSourceClass(className, DEFAULT_EXCLUSION_FILTER));
				}
			}
			return result;
		}

		public Set<SourceClass> getAnnotations() {
			Set<SourceClass> result = new LinkedHashSet<>();
			if (this.source instanceof Class) {
				Class<?> sourceClass = (Class<?>) this.source;
				for (Annotation ann : sourceClass.getDeclaredAnnotations()) {
					Class<?> annType = ann.annotationType();
					if (!annType.getName().startsWith("java")) {
						try {
							result.add(asSourceClass(annType, DEFAULT_EXCLUSION_FILTER));
						} catch (Throwable ex) {
							// An annotation not present on the classpath is being ignored
							// by the JVM's class loading -> ignore here as well.
						}
					}
				}
			} else {
				for (String className : this.metadata.getAnnotationTypes()) {
					if (!className.startsWith("java")) {
						try {
							result.add(getRelated(className));
						} catch (Throwable ex) {
							// An annotation not present on the classpath is being ignored
							// by the JVM's class loading -> ignore here as well.
						}
					}
				}
			}
			return result;
		}

		public Collection<SourceClass> getAnnotationAttributes(String annType, String attribute) throws IOException {
			Map<String, Object> annotationAttributes = this.metadata.getAnnotationAttributes(annType, true);
			if (annotationAttributes == null || !annotationAttributes.containsKey(attribute)) {
				return Collections.emptySet();
			}
			String[] classNames = (String[]) annotationAttributes.get(attribute);
			Set<SourceClass> result = new LinkedHashSet<>();
			for (String className : classNames) {
				result.add(getRelated(className));
			}
			return result;
		}

		private SourceClass getRelated(String className) throws IOException {
			if (this.source instanceof Class) {
				try {
					Class<?> clazz = ClassUtils.forName(className, ((Class<?>) this.source).getClassLoader());
					return asSourceClass(clazz, DEFAULT_EXCLUSION_FILTER);
				} catch (ClassNotFoundException ex) {
					// Ignore -> fall back to ASM next, except for core java types.
					if (className.startsWith("java")) {
						throw new NestedIOException("Failed to load class [" + className + "]", ex);
					}
					return new SourceClass(metadataReaderFactory.getMetadataReader(className));
				}
			}
			return asSourceClass(className, DEFAULT_EXCLUSION_FILTER);
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other || (other instanceof SourceClass &&
					this.metadata.getClassName().equals(((SourceClass) other).metadata.getClassName())));
		}

		@Override
		public int hashCode() {
			return this.metadata.getClassName().hashCode();
		}

		@Override
		public String toString() {
			return this.metadata.getClassName();
		}
	}


	/**
	 * {@link Problem} registered upon detection of a circular {@link Import}.
	 */
	private static class CircularImportProblem extends Problem {

		public CircularImportProblem(ConfigurationClass attemptedImport, Deque<ConfigurationClass> importStack) {
			super(String.format("A circular @Import has been detected: " +
									"Illegal attempt by @Configuration class '%s' to import class '%s' as '%s' is " +
									"already present in the current import stack %s", importStack.element().getSimpleName(),
							attemptedImport.getSimpleName(), attemptedImport.getSimpleName(), importStack),
					new Location(importStack.element().getResource(), attemptedImport.getMetadata()));
		}
	}

}
